﻿using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace Syspetro.Deploy.AuthorizationReq
{
    /// <summary>
    /// 角色等级权限
    /// </summary>
    public class RoleLevelAttribute : CustomAuthorizeAttribute
    {
        public RoleLevelAttribute(int level) : base(level, false) { }
    }
    /// <summary>
    /// 管理员权限
    /// </summary>
    public class AdminAttribute : CustomAuthorizeAttribute
    {
        public AdminAttribute() : base(1, true) { }
    }
    /// <summary>
    /// 权限
    /// </summary>
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
    public class CustomAuthorizeAttribute : AuthorizeAttribute
    {
        const string POLICY_PREFIX = "MinimumLevel";
        private int level = 0;
        private bool isadmin = false;

        public CustomAuthorizeAttribute(int level = -1, bool isAdmin = false)
        {
            this.level = level;
            this.isadmin = isAdmin;
            Policy = $"{POLICY_PREFIX}_{this.level}_{this.isadmin}";
        }
        public int Level
        {
            get
            {
                return level;
            }
            set
            {
                level = value;
                Policy = $"{POLICY_PREFIX}_{value}_{isadmin}";
            }
        }
        public bool IsAdmin
        {
            get
            {
                return isadmin;
            }
            set
            {
                isadmin = value;
                Policy = $"{POLICY_PREFIX}_{level}_{value}";
            }
        }
    }
    public class CustomPolicyProvider : IAuthorizationPolicyProvider
    {
        const string POLICY_PREFIX = "MinimumLevel";
        public DefaultAuthorizationPolicyProvider FallbackPolicyProvider { get; }

        public CustomPolicyProvider(IOptions<AuthorizationOptions> options)
        {
            FallbackPolicyProvider = new DefaultAuthorizationPolicyProvider(options);
        }

        public Task<AuthorizationPolicy> GetDefaultPolicyAsync() => FallbackPolicyProvider.GetDefaultPolicyAsync();

        public Task<AuthorizationPolicy> GetFallbackPolicyAsync() => FallbackPolicyProvider.GetFallbackPolicyAsync();

        public Task<AuthorizationPolicy> GetPolicyAsync(string policyName)
        {
            if (policyName.StartsWith(POLICY_PREFIX, StringComparison.OrdinalIgnoreCase))
            {
                var list = policyName.Split('_');
                if (list.Length >= 3)
                {
                    if (int.TryParse(list[1], out var level) && bool.TryParse(list[2], out var isadmin))
                    {
                        var policy = new AuthorizationPolicyBuilder(JwtBearerDefaults.AuthenticationScheme);
                        policy.AddRequirements(new CustomExtendRequirement(level, isadmin));
                        return Task.FromResult(policy.Build());
                    }
                }
            }
            return Task.FromResult<AuthorizationPolicy>(null);
        }
    }
    public class CustomExtendRequirement : IAuthorizationRequirement
    {
        public int Level { get; set; }
        public bool IsAdmin { get; set; }
        public CustomExtendRequirement(int level, bool isadmin)
        {
            Level = level;
            IsAdmin = isadmin;
        }
    }
    public class CustomExtendRequirementHandler : AuthorizationHandler<CustomExtendRequirement>
    {
        protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, CustomExtendRequirement requirement)
        {
            #region 处理验证逻辑
            bool tokenExists = true;
            if (context.User != null)
            {
                if (!context.User.Claims.Any())
                {
                    context.Fail();
                    return Task.CompletedTask;
                }
                if (requirement.IsAdmin && context.User.HasClaim(c => c.Type == "IsAdmin"))
                {
                    var admin = context.User.FindFirst(c => c.Type == "IsAdmin").Value;
                    if (admin == "true" || admin == "True")
                        tokenExists = true;
                    else
                        tokenExists = false;
                }
                if (tokenExists && requirement.Level > -1 && context.User.HasClaim(c => c.Type == "Level"))
                {

                    var levelstring = context.User.FindFirst(c => c.Type == "Level").Value;
                    if (int.TryParse(levelstring, out var level))
                    {
                        if (requirement.Level <= level) tokenExists = true;
                        else tokenExists = false;
                    }
                    else tokenExists = false;
                }
            }
            if (tokenExists)
            {
                context.Succeed(requirement); // 显式的声明验证成功
            }
            else
            {
                context.Fail();// 显式的声明验证失败
            }
            #endregion
            return Task.CompletedTask;
        }
    }
}
